2. When developing code with other programmers, which is standard for most
corporate or team projects, it becomes fundamentally important to maintain
good authoring practices in order maintaom your sanity.
On the next slide, we're going to look at a number of ways in wich you can
clean up your code, organize ot better, and improve the quality so that others
can use it.
4. Prototypal Inheritance
• Unlike inheritance in other Object-
Oriented language, prototypes do not
inherit their properties from other
prototypes or other constructors; they
inherit them from physical objects
5. Examples of Prototypal Inheritance
// Create the constructor for a Person object
function Person( name ) {
this.name = name;
}
// Add a new method to the Person object
Person.prototype.getName = function() {
return this.name;
};
// Create a new User object constructor
function User( name, password ) {
// Notice that this does not support graceful overloading/inheritance
// e.g. being able to call the super class constructor
this.name = name;
this.password = password;
};
// The User object inherits all of the Person object's methods
User.prototype = new Person();
// We add a method of our own to the User object
User.prototype.getPassword = function() {
return this.password;
};
6. Classical Inheritance
http://javascript.crockford.com/inheritance.html.
• Function.prototype.method: This serves as a simple way of attaching a
function to the prototype of a constructor. This particular clause works because all
constructors are functions, and thus gain the new “method” method.
• Function.prototyope.inherits: This function can be used to provide simple
single-parent inheritance. The bulk of the code in this function centers around
the ability to call this.uber('methodName') in any of your object methods,
and have it execute the parent object’s method that it’s overwriting.
This is one aspect that is not built into JavaScript’s inheritance model.
• Function.prototype.swiss: This is an advanced version of the .method()
function which can be used to grab multiple methods from a single parent object.
When used together with multiple parent objects, you can have a form of
functional, multiple inheritance.
8. The Base Library
• http://dean.edwards.name/weblog/2006/03/base/
– More examples : http://dean.edwards.name/base/
9. Examples of Dean Edwards’s Base Library for Simple Class Creation and Inheritanc
// Create a new Person class
var Person = Base.extend({
// The constructor of the Person class
constructor: function( name ) {
this.name = name;
},
A simple method of the Person class
getName: function() {
return this.name;
}
});
// Create a new User class that inherits from the Person class
var User = Person.extend({
// Create the User class constructor
constructor: function( name, password ) {
// which, in turn calls the parent classes' constructor method
this.base( name );
this.password = password;
},
// Create another, simple, method for the User
getPassword: function() {
return this.password;
}
});
10. • Base.extend( ... );: This expression is used to create a
new base constructor object. This function takes one
property, a simple object containing properties and values,
all of which are added to the object and used as its
prototypal methods.
• Person.extend( ... );: This is an alternate version of the
Base.extend() syntax. All constructors created using the
.extend() method gain their own .extend() method, meaning
that it’s possible to inherit directly from them. In Listing on
the previouse slide you create the User constructor by
inheriting directly from the original Person constructor.
• this.base();: Finally, the this.base() method is used to call
a parent function that has been overridden. You’ll notice that
this is rather different from the this.uber() function that
Crockford’s classical library used, as you don’t need to
provide the name of the parent function (which can help to
really clean up and clarify your code). Of all the object-
oriented JavaScript libraries, Base’s overridden parent
method functionality is the best.
12. Two Functions Used by Prototype to Simulate Object-Oriented JavaScript Code
// Create a global object named 'Class'
var Class = {
// it has a single function that creates a new object constructor
create: function() {
// Create an anonymous object constructor
return function() {
// This calls its own initialization method
this.initialize.apply(this, arguments);
}
}
}
// Add a static method to the Object object which copies
// properties from one object to another
Object.extend = function(destination, source) {
// Go through all of the properties to extend
for (property in source) {
// and add them to the destination object
destination[property] = source[property];
}
// return the modified object
return destination;
}
13. Class.create(): This function simply returns an anonymous
•
function wrapper that can be used as a constructor. This simple
constructor does one thing: it calls and executes the initialize
property of the object. This means that there should be, at the very
least, an initialize property containing a function on your object;
otherwise, the code will throw an exception.
Object.extend(): This simply copies all properties from one object
•
into another. When you use the prototype property of constructors
you can devise a simpler form of inheritance (simpler than the
default prototypal inheritance that’s available in JavaScript).
14. Examples of How Prototype Uses Object-Oriented Functions to Extend the Default
Operations of a String in JavaScript
// Add additional methods to the String prototype
Object.extend(String.prototype, {
// A new Strip Tags function that removes all HTML tags from the string
stripTags: function() {
return this.replace(/</?[^>]+>/gi, '');
// An example of the stripTags() method
},
// You can see that it removes all the
//HTML from the string
// Converts a string to an array of characters
// and leaves us with a clean textonly string
toArray: function() {
quot;<b><i>Hello</i>,
return this.split('');
world!quot;.stripTags() == quot;Hello, world!quot;
},
// Converts quot;foobarquot; text to quot;fooBarquot;
// An example of toArray() method
//'camel' text
// We get the fourth character in the string
camelize: function() {
quot;abcdefgquot;.toArray()[3] == quot;dquot;
// Break up the string on dashes
var oStringList = this.split('');
// An example of the camelize() method
// It converts the old string to the new format.
// Return early if there are no dashes
quot;backgroundcolorquot;.camelize() == quot;backgroundColorquot;
if (oStringList.length == 1)
return oStringList[0];
// Optionally camelize the start of the string
var camelizedString = this.indexOf('') == 0
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
: oStringList[0];
// Capitalize each subsequent portion
for (var i = 1, len = oStringList.length; i < len; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
// and return the modified string
return camelizedString;
}
});
15. // Create a new Person object with dummy constructor
var Person = Class.create();
Prototype’s Helper Functions
// Copy the following functions into the Person prototype
for Creating Classes and
Object.extend( Person.prototype, {
Implementing Simple Inheritance
// The function called immediately by the Person constructor
initialize: function( name ) {
this.name = name;
},
// A simple function for the Person object
getName: function() {
return this.name;
}
});
// Create a new User object with a dummy constructor
var User = Class.create();
// The User object inherits all the functions of its parent class
User.prototype = Object.extend( new Person(), {
// Overwrite the old initialize function with the new one
initialize: function( name, password ) {
this.name = name;
this.password = password;
},
// and add a new function to the object
getPassword: function() {
return this.password;
}
});
17. Namespacing
• An important but simple technique
that you can use to clean up and
simplify your code is the concept of
namespacing
18. Namespacing in JavaScript and How It’s Implemented
// Create a default, global, namespace
var YAHOO = {};
// Setup some child namespaces, using objects
YAHOO.util = {};
// Create the final namespace, which contains
//a property with a function
YAHOO.util.Event = {
addEventListener: function(){ ... }
};
// Call the function within that particular namespace
YAHOO.util.Event.addEventListener( ... )
19. Packaging and Namespacing in Dojo
<html>
<head>
<title>Accordion Widget Demo</title>
<!— Include the Dojo Framework >
<script type=quot;text/javascriptquot; src=quot;dojo.jsquot;></script>
<!— Include the different Dojo Packages >
<script type=quot;text/javascriptquot;>
// Two different packages are imported and used to create
// an Accordian Container widget
dojo.require(quot;dojo.widget.AccordionContainerquot;);
dojo.require(quot;dojo.widget.ContentPanequot;);
</script>
</head>
<body>
<div dojoType=quot;AccordionContainerquot; labelNodeClass=quot;labelquot;>
<div dojoType=quot;ContentPanequot; open=quot;truequot; label=quot;Pane 1quot;>
<h2>Pane 1</h2>
<p>Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin…</p>
</div>
<div dojoType=quot;ContentPanequot; label=quot;Pane 2quot;>
<h2>Pane 2</h2>
<p>Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin…</p>
</div>
<div dojoType=quot;ContentPanequot; label=quot;Pane 3quot;>
<h2>Pane 3</h2>
<p>Nunc consequat nisi vitae quam. Suspendisse sed nunc. Proin…</p>
</div>
</div>
</body>
</html>
20. Packaging and Namespacing Within the Yahoo UI Library
<html>
<head>
<title>Yahoo! UI Demo</title>
<! Import the main Yahoo UI library >
<script type=quot;text/javascriptquot; src=quot;YAHOO.jsquot;></script>
<! Import the events package >
<script type=quot;text/javascriptquot; src=quot;event.jsquot;></script>
<! Use the imported Yahoo UI library >
<script type=quot;text/javascriptquot;>
// All Yahoo events and utilities are contained within the YAHOO
// namespace, and subdivided into smaller namespaces (like 'util')
YAHOO.util.Event.addListener( 'button', 'click', function() {
alert( quot;Thanks for clicking the button!quot; );
});
</script>
</head>
<body>
<input type=quot;buttonquot; id=quot;buttonquot; value=quot;Click Me!quot;/>
</body>
</html>
21. Cleaning Up Your Code
• http:// www.jslint.com/
JSLint has a set of built-in rules that spot pieces of
code that could cause you or others problems
later, developed by Douglas Crockford
• Some JSlint rules :
– Variable declaration
– != and == vs !== and ===
– Blocks and brackets
– Semicolons
22. Variable Declaration
• One smart requirement that JSLint puts forth is that all
variables used in your program must be declared
before they are used
– not declare the variable first before use can cause
confusion as to its actual scope
// Incorrect variable use
foo = 'bar';
// Correct variable delcaration
var foo;
...
foo = 'bar';
23. != and == vs. !== and ===
A common mistake that developers are susceptible to is the lack of
•
understanding of false values in JavaScript. In JavaScript, null, 0, ‘’,
false, and undefined are all equal (==) to each other, since they all
evaluate to false. This means that if you use the code test ==
false, it will evaluate true if test is also undefined or equal to null,
which may not be what you want
This is where !== and === become useful. Both of these operators
•
look at the explicit value of the variable (such as null), not just what
it is equivalent to (such as false). JSLint requires that anytime you
use != or == against a falselike value, you must use !== or ===
instead
24. Examples of How != and == Differ from !== and ===
// Both of these are true
null == false
0 == undefined
// You should use !== or === instead
null !== false
false === false
25. Blocks and Brackets
• JSlint have a rule that single-line block cannot be used.
Such as in if(), while() or for() statement
// This code is legal, normal, Javascript
if ( dog == cat )
if ( cat == mouse )
mouse = quot;cheesequot;;
// JSLint requires that it be written like this:
if ( dog == cat ) {
if ( cat == mouse ) {
mouse = quot;cheesequot;;
}
}
26. Semicolons
Statements That Need to Have Semicolons
// Be sure to include semicolons at the end
//of all statements, if you plan on
// compressing your Javascript code
var foo = 'bar';
var bar = function(){
alert('hello');
};
bar();
27. Compression
• An essential aspect of JavaScript library distribution is the
use of code compressors to save on bandwidth
• There are three types of javaScript compressors :
– Compressors that simply remove all extraneous white
space and comments, leaving nothing but the essential
code.
– Compressors that remove the white space and comments
but also change all variable names to be smaller.
– Compressors that do the previous, but also minimize the
size of all words in your code, not just variable names.
• The compressor that going to discuss is :
– JSMin : falls under first compressor
– Packer : falls under the third
28. JSMin
• On online version can be found here :
http://www.crockford.com/javascript/jsmin.html
• The next slide will give you a feel what
happens to the code once it's been passed
through JSMin
29. Code for Determining a User’s Browser
// (c) 2001 Douglas Crockford
// 2001 June 3
// The is object is used to identify the browser. Every browser edition
// identifies itself, but there is no standard way of doing it, and some of
// the identification is deceptive. This is because the authors of web
// browsers are liars. For example, Microsoft's IE browsers claim to be
// Mozilla 4. Netscape 6 claims to be version 5.
var is = {
ie: navigator.appName == 'Microsoft Internet Explorer',
java: navigator.javaEnabled(),
ns: navigator.appName == 'Netscape',
ua: navigator.userAgent.toLowerCase(),
version: parseFloat(navigator.appVersion.substr(21)) ||
parseFloat(navigator.appVersion),
win: navigator.platform == 'Win32'
}
is.mac = is.ua.indexOf('mac') >= 0;
if (is.ua.indexOf('opera') >= 0) {
is.ie = is.ns = false;
is.opera = true;
}
if (is.ua.indexOf('gecko') >= 0) {
is.ie = is.ns = false;
is.gecko = true;
}
30. A Compressed Copy of the Code in Previous Listing
// Compressed code
var is={ie:navigator.appName=='Microsoft Internet Explorer',java:
navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:
navigator.userAgent.toLowerCase(),version:parseFloat(
navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:
navigator.platform=='Win32'} is.mac=is.ua.indexOf('mac')>=0;if(
is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}
31. Packer
• Packer is by far the most powerful JavaScript
compressor available. Developed by Dean Edwards, it
serves as a way to completely reduce the size of your
code and expand and execute it again on the fly
• The code that Packer generates has a couple hundred
bytes of overhead (in order to be able to extract itself),
so it’s not perfect for extremely small code (JSMin
would be better for that). However, for large files, it is
absolutely perfect
• An online version of the script is available at :
http://dean.edwards.name/packer/
32. Portion of Code Compressed Using Packer
eval(function(p,a,c,k,e,d){e=function(c){return
c.toString(36)};if(!''.replace(/^/,
String)){while(c){d[c.toString(a)]=k[c]||
c.toString(a)}k=[(function(e){return
d[e]})];e=(function(){return'w+'});c=1};while(c)
{if(k[c]){p=p.replace(new
RegExp('b'+e(c)+'b','g'),k[c])}}return p}('u
1={5:2.f=='t s
r',h:2.j(),4:2.f=='k',3:2.l.m(),n:7(2.d.o(p))||
7(2.d),q:2.g=='i'}1.
b=1.3.6('b')>=0;a(1.3.6('c')>=0)
{1.5=1.4=9;1.c=e}a(1.3.6('8')>=0){1.5=
1.4=9;1.8=e}',31,31,'|is|navigator|ua|ns|ie....
33. Distribution
• If you develop an interesting piece of
code and wish to let the world use it
however they wish, you can use
service such as the JavaScript Archive
Network (JSAN) - http://openjsan.org/
• If you create a plugin on a certain
library such as jQuery, you can use
the plugin repository that jQuery
provided